<template>
    <div class="container">
        <div class="left-board">
            <el-scrollbar class="left-scrollbar">
                <!-- 左边表单项 -->
                <div class="component-list">
                    <div v-for="(item,index) in leftComponents" :key="index">
                        <div class="components-title">
                            {{item.title}}
                        </div>
                        <draggable
                            class="components-draggable"
                            :list="item.list"
                            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
                            :clone="cloneComponent"
                            draggable=".components-item"
                            :sort="false"
                            @end="onEnd"
                        >
                             <div
                                v-for="(element, index) in item.list"
                                :key="index"
                                class="components-item"
                                @click="addComponent(element)"
                              >
                                <div class="components-body">
                                  {{ element.__config__.label }}
                                </div>
                              </div>
                        </draggable>
                    </div>
                </div>
            </el-scrollbar>
        </div>

        <!-- 中间 -->
        <div class="center-board">
           <div class="action-bar">
              <!-- <el-button icon="el-icon-view" type="text" @click="showJson">
                查看json
              </el-button> -->
              <el-button icon="el-icon-download" type="text" @click="download">
                导出vue文件
              </el-button>
              <!-- <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">
                复制代码
              </el-button>
              <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
                清空
              </el-button> -->
            </div>
            <el-scrollbar class="center-scrollbar">
              <el-row class="center-board-row" :gutter="formConf.gutter">
                  <el-form 
                    :size="formConf.size"
                    :label-position="formConf.labelPosition"
                    :disabled="formConf.disabled"
                    :label-width="formConf.labelWidth + 'px'"
                  >
                      <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
                         <draggable-item
                          v-for="(item, index) in drawingList"
                          :key="item.renderKey"
                          :drawing-list="drawingList"
                          :current-item="item"
                          :index="index"
                          :active-id="activeId"
                          :form-conf="formConf"
                          @activeItem="activeFormItem"
                          @copyItem="drawingItemCopy"
                          @deleteItem="drawingItemDelete"
                        />
                      </draggable>
                      <div v-show="!drawingList.length" class="empty-info">
                        从左侧拖入或点选组件进行表单设计
                      </div>
                  </el-form>
              </el-row>
            </el-scrollbar>
        </div>
        <!-- 生成类型 -->
        <code-type-dialog
          :visible.sync="dialogVisible" 
          title="选择生成类型"
          :show-file-name="showFileName"    
          @confirm="generate"       
        />
    </div>
</template>

<script>
import draggable from 'vuedraggable'
import { 
    inputComponents,selectComponents,layoutComponents, formConf 
} from '@/config/config-component'
import drawingDefalut from '@/config/drawingDefalut'
import { getIdGlobal, saveIdGlobal, saveDrawingList } from '@/utils/db'
import { deepClone, titleCase, beautifierConf } from '@/utils/index'
import DraggableItem from '@/views/demo/DraggableItem'
import CodeTypeDialog from './CodeTypeDialog.vue'
import { debounce } from 'throttle-debounce'
import { vueTemplate } from './generator/html'
import { vueScript } from './generator/html'
import { cssStyle } from './generator/html'
import { makeUpJs } from './generator/js'
import { makeUpHtml } from './generator/html'
import { makeUpCss } from './generator/css'
import { saveAs } from 'file-saver'

let tempActiveData
const idGlobal = getIdGlobal()
    export default {
        components: {
            draggable,
            DraggableItem,
            CodeTypeDialog
        },
        data() {
            return {
                // 导出vue文件弹窗
                dialogVisible: false,
                // 显示文件名
                showFileName: false,
                // form data
                formData: {},
                saveDrawingListDebounce: debounce(340, saveDrawingList),
                saveIdGlobalDebounce: debounce(340, saveIdGlobal),
                inputComponents,
                selectComponents,
                layoutComponents,
                leftComponents: [
                    {
                        title: '输入型组件',
                        list: inputComponents
                    },
                    {
                        title: '选择型组件',
                        list: selectComponents
                    },
                    {
                        title: '布局型组件',
                        list: layoutComponents
                    }
                ],
                formConf,
                // 表单默认显示的配置组件
                drawingList: drawingDefalut,
                labelWidth: 100,
                idGlobal,
                activeId: drawingDefalut[0].__config__.formId,
                activeData: drawingDefalut[0]   // 右侧的编辑表单
            }
        },
        mounted() {
            this.activeFormItem(this.drawingList[0])
        },
        watch: {
          // 监听面板的组件列表
          drawingList: {
            handler(val) {
              this.saveDrawingListDebounce(val)
              if (val.length === 0) this.idGlobal = 100
            },
            immediate: true
          },
          idGlobal: {
              handler(val) {
                this.saveIdGlobalDebounce(val)
              },
              immediate: true
          }
        },
        methods: {
          addComponent(element) {
             const clone = this.cloneComponent(element);
             this.drawingList.push(clone)
             this.activeFormItem(clone);
          },
          cloneComponent(origin) {
              const clone = deepClone(origin)
              const config = clone.__config__
               config.formId = ++this.idGlobal
               console.log(this.idGlobal);
              config.span = this.formConf.span // 生成代码时，会根据span做精简判断
              this.createIdAndKey(clone)
              clone.placeholder !== undefined && (clone.placeholder += config.label)
              tempActiveData = clone
              return tempActiveData
          },
          createIdAndKey(item) {
             const config = item.__config__
             config.formId = ++this.idGlobal
             // 随机生成key
             config.renderKey = `${config.formId}${+new Date()}`
             if(config.layout === 'colFormItem') {
                item.__vModel__ = `field${this.idGlobal}`
             }else if(config.layout === 'rowFormItem') {
                config.componentName = `row${this.idGlobal}`
                !Array.isArray(config.children) && (config.children=[])
                delete config.label
             }
             if(Array.isArray(config.children)) {
               config.children = config.children.map(childItem => this.createIdAndKey(childItem))
             }
             return item;
          },
          fetchData(component) {
              // 该方法不需要 
             // const { dataType, method, url} = component.__config__
          },
          activeFormItem(currentItem) {
            this.activeData = currentItem;
            this.activeId = currentItem.__config__.formId
          },
          onEnd(obj) {
              console.log(obj);
          },
          drawingItemCopy(item, list) {
            let clone = deepClone(item)
            clone = this.createIdAndKey(clone)
            list.push(clone)
            this.activeFormItem(clone)
          },
          drawingItemDelete(index, list) {
            list.splice(index, 1)
            this.$nextTick(() => {
              const len = this.drawingList.length
              if (len) {
                this.activeFormItem(this.drawingList[len - 1])
              }
            })
          },
          download() {
            this.dialogVisible = true;
            this.showFileName = true;
            this.operationType = 'download'
          },
          generate(data) {
            const func = this[`exec${titleCase(this.operationType)}`]
            // console.log('AAAAAAAA',func);
            this.generateConf = data;
            func && func(data)
          },
          execDownload(data) {
             const codeStr = this.generateCode()
             const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
             saveAs(blob, data.fileName)
          },
          generateCode() {
            // 获取form的类型 是弹窗还是页面
            const { type } = this.generateConf
            this.AssembleFormData();
            // 组装vue的JS html css部分
               const script = vueScript(makeUpJs(this.formData, type))
              const html = vueTemplate(makeUpHtml(this.formData, type))
              const css = cssStyle(makeUpCss(this.formData))
              return html + script + css
          },
          // 组装formdata数据
          AssembleFormData() {
             this.formData = {
               fields: deepClone(this.drawingList),
               ...this.formConf
             }
          }
        }
    }
</script>

<style lang="scss" scoped>
$selectedColor: #f6f7ff;
.container {
  position: relative;
  width: 100%;
  height: 100%;
}
.left-board {
  width: 260px;
  position: absolute;
  left: 0;
  top: 0;
  height: 100vh;
}
.left-scrollbar{
  height: calc(100vh - 42px);
  overflow: hidden;
}
.components-draggable{
  padding-bottom: 20px;
}
.center-scrollbar {
  height: calc(100vh - 42px);
  overflow: hidden;
  border-left: 1px solid #f1e8e8;
  border-right: 1px solid #f1e8e8;
  box-sizing: border-box;
}
.center-board {
  height: 100vh;
  width: auto;
  margin: 0 350px 0 260px;
  box-sizing: border-box;
}
.action-bar{
  position: relative;
  height: 42px;
  text-align: right;
  padding: 0 15px;
  box-sizing: border-box;;
  border: 1px solid #f1e8e8;
  border-top: none;
  border-left: none;
  .delete-btn{
    color: #F56C6C;
  }
}
.center-board-row {
  padding: 12px 12px 15px 12px;
  box-sizing: border-box;
  & > .el-form {
    // 69 = 12+15+42
    height: calc(100vh - 69px);
  }
}
.empty-info{
  position: absolute;
  top: 46%;
  left: 0;
  right: 0;
  text-align: center;
  font-size: 18px;
  color: #ccb1ea;
  letter-spacing: 4px;
}
.components-list {
  padding: 8px;
  box-sizing: border-box;
  height: 100%;
  .components-item {
    display: inline-block;
    width: 40%;
    margin: 1%;
    transition: transform 0ms !important;
  }
}
.components-body {
  padding: 8px 10px;
  background: #f6f7ff;
  font-size: 12px;
  cursor: move;
  border: 1px dashed #000;
  border-radius: 3px;
  // .svg-icon{
  //   color: #777;
  //   font-size: 15px;
  // }
  &:hover {
    border: 1px dashed #787be8;
    color: #787be8;
    // .svg-icon {
    //   color: #787be8;
    // }
  }
}
.drawing-board {
  height: 100%;
  position: relative;
  .components-body {
    padding: 0;
    margin: 0;
    font-size: 0;
  }
  .sortable-ghost {
    position: relative;
    display: block;
    overflow: hidden;
    &::before {
      content: " ";
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      height: 3px;
      background: rgb(89, 89, 223);
      z-index: 2;
    }
  }
  .components-item.sortable-ghost {
    width: 100%;
    height: 60px;
    background-color: #f6f7ff;
  }
  .active-from-item {
    & > .el-form-item{
      background: #f6f7ff;
      border-radius: 6px;
    }
    & > .drawing-item-copy, & > .drawing-item-delete{
      display: initial;
    }
    & > .component-name{
      color: #409EFF;
    }
  }
  .el-form-item{
    margin-bottom: 15px;
  }
}

</style>